﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common;
using System.Net;
using System.IO;
using System.Runtime.InteropServices;

    

/* Sample Invocation of operations in this driver
 *  * 
       IList<View.VPort> allPortsList1 = GetAllPortsFromPlatform();
       foreach (View.VPort port in allPortsList1)
       {
           if (Role.ContainsRole(port, RoleSensor.RoleName) && port.GetInfo().ModuleFacingName() == "Ismart" )
           {
                    
               View.VPort enviPort = port;
               View.VCapability enviPortCapability = GetCapability(port, Globals.UserSystem);
               View.VCapability notificationPortCapability = GetCapability(enviPort, Globals.UserSystem);
               IList<View.VParamType> msgParams = new List<View.VParamType>();
               msgParams.Add(new ParamType(ParamType.SimpleType.text, "", "2", "subject"));

               IList<View.VParamType> temp  = enviPort.Invoke(RoleSensor.RoleName, RoleSensor.OpGetStatus, msgParams,
                this.ControlPort, notificationPortCapability, this.ControlPortCapability);

               logger.Log(" Response :  {0} ", ((string)temp[0].Value()).ToString());

           }
       }

       */

namespace DriverIsmart
{
    [System.AddIn.AddIn("DriverIsmart")]
    public unsafe class DriverIsmart : Common.ModuleBase
    {
      

        private Port IsmartPort;
        private string DeviceIP;
        private bool[] status = new bool[5];
        public unsafe override void Start()
        {
          
            logger.Log("{0} started . .  .",ToString());

           

            string[] words = moduleInfo.Args();
            DeviceIP = words[0];
            status[0] = status[1] = status[2] = status[3] = status[4] = false;
            
            // ..... initialize the list of roles we are going to export
            List<View.VRole> listRole = new List<View.VRole>() {new RoleNotifications()};

            RoleSensor IsmartRole = new RoleSensor();
            listRole.Add(IsmartRole);

            //.................instantiate the port
            View.VPortInfo portInfo = GetPortInfoFromPlatform("Ismart");
            IsmartPort = InitPort(portInfo);

            //..... bind the port to roles and delegates
            BindRoles(IsmartPort, listRole, OnOperationInvoke);

            //.................register the port after the binding is complete
            RegisterPortWithPlatform(IsmartPort);
        }


        public IList<View.VParamType> OnOperationInvoke(string roleName, String opName, IList<View.VParamType> parameters)
        {
            List<View.VParamType> retVals = new List<View.VParamType>();
           
            switch (opName)
            {
                case RoleSensor.OpSwitchOff:
                {
                    string subject = (string)parameters[0].Value();
                    bool current = status[int.Parse(subject)-1];

                    if (current) //  can "switch it off" only when its on
                    {
                        bool success = SwitchSocket(int.Parse(subject),"off");
                        retVals.Add(new ParamType(ParamType.SimpleType.binary, "", success, "result"));
                    }
                    else
                    {
                        retVals.Add(new ParamType(ParamType.SimpleType.binary, "", null, "result"));
                    }

                  
                                   
                }
                break;
            
                case RoleSensor.OpSwitchOn:
                {
                    string subject = (string)parameters[0].Value();
                    bool current = status[int.Parse(subject) - 1];

                    if (!current) //  can "switch it on" only when its off
                    {
                        bool success = SwitchSocket(int.Parse(subject),"on");
                        retVals.Add(new ParamType(ParamType.SimpleType.binary, "", success, "result"));
                    }
                    else
                    {
                        retVals.Add(new ParamType(ParamType.SimpleType.binary, "", null, "result"));
                    }

                }       
                break;

                case RoleSensor.OpGetStatus:
                {

                    string status = GetStatus(); // respond with xml file containing all the data
                    retVals.Add(new ParamType(ParamType.SimpleType.text, "", status, "status")); 

                }
                break;


                default:
                logger.Log("Invalid operation {0}", opName);
                break;
                    
            }
            
            return retVals;
        }


        private bool SwitchSocket(int socketNumber,string action)
        {
            bool new_status;
            new_status = (action.Equals("off")) ? false : true;

            String url = "http://" + DeviceIP +"/leds.cgi?led="+(socketNumber +2).ToString();
            logger.Log("Connecting to Ismart Device at {0}",url);
             
            WebRequest request = WebRequest.Create(url);
            WebResponse response = request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);

            string content = reader.ReadToEnd(); //logger.Log("Response from ismart is {0}", content);
            if (content.Contains("Success!")) { status[socketNumber - 1] = new_status; return true; }
            else return false;
        }

        private string GetStatus()
        {
            String url = "http://" + DeviceIP + "/status.xml";
            WebRequest request = WebRequest.Create(url);
            WebResponse response = request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
            string XmlStatus = reader.ReadToEnd(); //logger.Log("Status Response from ismart is {0}", XmlStatus);
            return XmlStatus;
        }
              


        public override void Stop()
        {
            
        }

        public override void PortRegistered(View.VPort port)
        {
            
        }

        public override void PortDeregistered(View.VPort port)
        {
            
        }
    }
}
